home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / pascal / tty.zip / TTY.PAS < prev   
Pascal/Delphi Source File  |  1988-06-12  |  4KB  |  133 lines

  1. program TTY;
  2.  
  3. uses
  4.     DOS,CRT;
  5.  
  6. const
  7.      RBR = $3F8;        {Port address - RX Buffer Register}
  8.      THR = $3F8;        {Transmit Hold Register}
  9.      DLL = $3F8;        {Low byte of divisor}
  10.      DLM = $3F9;        {High Byte of Divisor}
  11.      IER = $3F9;         {Overlays INT Enable Register}
  12.      LCR = $3FB;        {Line Control Register}
  13.      MCR = $3FC;        {Modem Control Register}
  14.      LSR = $3FD;        {Line Status Register}
  15.  
  16.      BAUD300   = 384;            {300 Baud Divisor}
  17.      BAUD1200  = 96;        {1200 Baud Divisor}
  18.      RTS       = $02;            {Mask for ReadyToSend}
  19.      ERBFI     = $01;            {Mask to enable Receive INT's}
  20.      THRE      = $20;            {Mask for THRE}
  21.      TWOSTOP   = $04;            {Mask for 2 stop bits (110 baud only)}
  22.      ONESTOP   = $00;            {Mask for 1 stop bit}
  23.      DTR       = $01;            {Mask for DTR}
  24.      DLAB      = $80;            {Mask for DLAB}
  25.      NOPARITY  = $00;            {Mask for no parity}
  26.      EIGHTBITS = $03;            {Mask for 8 bits/char}
  27.  
  28.      OCW1      = $21;            {Mask for enable bits for 8259}
  29.      OCW2      = $20;            {Port for 8259 Commands}
  30.      NSEOI     = $20;            {Non-specific End-Of-Interrupt Command}
  31.      OUT2      = $08;           {Mask for OUT2}
  32.      IRQ4      = $10;           {Mask to dis/enable hardware int level 4}
  33.      PORT1INT  = 12;            {Int vector number for IRQ4}
  34.  
  35.      QUEUEMAX  = 255;           {Max queue subscript, 2^n-1}
  36.  
  37. var
  38.  
  39.    queue : array [0..QUEUEMAX] of byte;  {Circular buffer}
  40.    queueIn : integer;
  41.    queueOut : integer;    {Buffer pointers}
  42.    oldVector : pointer;                  {Storage for old INT vector}
  43.    ch : char;                            {Keyboard Char}
  44.    temp : integer;
  45.  
  46. procedure InterruptsOn; inline($FB); {Turn on interrupts}
  47.  
  48. {$IFOPT R+}              {Don't forget to turn Range Checking on...}
  49. {$DEFINE RANGE}
  50. {$ENDIF}
  51.  
  52. {$R-}
  53.  
  54. procedure Port1ISR; Interrupt; {INT Service Routine for port 1}
  55. begin
  56.      InterruptsOn;
  57.      queueIn := Succ(queueIn) and QUEUEMAX;
  58.      if queueIn = queueOut then                {Queue full, put pointer back}
  59.         queueIn := Pred(queueIn) and QUEUEMAX;
  60.      queue[queueIn] := Port[RBR];
  61.      Port[OCW2] := NSEOI
  62. end;
  63.  
  64. {$IFDEF RANGE}
  65. {$R+}
  66. {$ENDIF}
  67.  
  68. {$F+}
  69.  
  70. Procedure RestoreIntVec;  {Exit proc to restore int vector}
  71. begin                     {shutoff ints and drop dtr}
  72.      Port[IER] := 0;                    {INTs off at UART}
  73.      Port[OCW1] := Port[OCW1] or IRQ4;  {INTs off at 8259}
  74.      Port[MCR] := 0;                    {DTR, RTS, OUT2 off}
  75.      SetIntVec(PORT1INT,oldVector)
  76. end;
  77.  
  78. {$F-}
  79.  
  80. begin
  81.      Writeln('GEnie Borland RoundTable Sample Dumb Terminal');
  82.      Writeln('Using COM1 at 1200 baud, 8 data bits, no parity, 1 stop bit');
  83.      Writeln('Press Alt-X to exit.');
  84.      CheckBreak := FALSE;
  85.      DirectVideo := TRUE;
  86.      queueIn := 0;
  87.      queueOut := 0;
  88.      Port[IER] := 0;                    {Disable UART INT's}
  89.  
  90. {Here's where we take over the comm interrupt}
  91.  
  92.      GetIntVec(PORT1INT,oldVector);
  93.      exitProc := Addr(RestoreIntVec);
  94.      SetIntVec(PORT1INT,Addr(Port1ISR));
  95.  
  96. {Initialize the UART}
  97.  
  98.      Port[LCR] := Port[LCR] or DLAB;    {Allow access to Divisor}
  99.      Port[DLL] := Lo(BAUD1200);         {Baud Rate to 1200}
  100.      Port[DLM] := Hi(BAUD1200);         {Ditto...}
  101.      Port[LCR] := EIGHTBITS or ONESTOP or NOPARITY;
  102.      Port[MCR] := DTR or RTS or OUT2;
  103.  
  104. {Turn on INTs at 8259}
  105.  
  106.      Port[OCW1] := Port[OCW1] and not (IRQ4);
  107.      if Port[LSR] <> 0 then;          {Clear any errors}
  108.      if Port[RBR] <> 0 then;          {Clear trash from RX buffer}
  109.      Port[IER] := ERBFI;              {Enable UART RX INTs}
  110.      repeat
  111.            while queueIN <> queueOut do
  112.            begin
  113.                 temp := Succ(queueOut) and QUEUEMAX;
  114.                 Write(Char(queue[temp] and $7F));  {Strip Hi Bit}
  115.                 queueOut := TEMP;
  116.            end;
  117.      if KeyPressed then
  118.         if Port[LSR] and THRE <> 0 then
  119.            begin
  120.                 ch := ReadKey;
  121.                 if (ch = #0) and KeyPressed then
  122.                 begin
  123.                      ch := Readkey;
  124.                      if ch = #45 then
  125.                      Halt     {Pressed Alt-X, exit}
  126.                 end
  127.                 else
  128.                      Port[THR] := Byte(ch)
  129.            end
  130.      until FALSE;
  131.  end.
  132.  
  133.